package ar.com.e2solver.solver;

import ar.com.e2solver.model.Piece;
import ar.com.e2solver.model.Puzzle;

public class Individual {

	private Puzzle thePuzzle;
	private int fitnessValue = -1;
	
	public Individual(Puzzle puzzle){
		this.thePuzzle = puzzle; 
	}
	
	private void populateFitness() {
		int fitness = 0;
		
		for(int i = 0; i < getPuzzle().getRowsNumber(); i++){
			for(int j = 0; j < getPuzzle().getColumnNumbers(); j++){
				Piece piece = thePuzzle.getPieceAt(i, j);
				
				if(i < thePuzzle.getRowsNumber() - 1 && piece.getBottom().equals(thePuzzle.getPieceAt(i+1, j).getTop())){
					fitness++;
				}
				
				if(j < thePuzzle.getColumnNumbers() - 1 && piece.getRight().equals(thePuzzle.getPieceAt(i, j+1).getLeft())){
					fitness++;
				}
			}
		}
			
		this.fitnessValue = fitness;
	}

	public Puzzle getPuzzle() {
		return thePuzzle;
	}

	public int getFitnessValue() {
		if(fitnessValue < 0){
			populateFitness();
		}
		return fitnessValue;
	}
	
	public int getMaxPossibleFitness() {
		int rows = this.getPuzzle().getRowsNumber();
		int cols = this.getPuzzle().getColumnNumbers();
		
		return ((cols - 1) * rows) + ((rows - 1) * cols);
	}
	
	@Override
	public String toString() {
		
		return "(" + System.identityHashCode(this) + " -> " + this.getFitnessValue() + ")";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((thePuzzle == null) ? 0 : thePuzzle.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Individual other = (Individual) obj;
		if (this.getFitnessValue() != other.getFitnessValue())
			return false;
		if (thePuzzle == null) {
			if (other.thePuzzle != null)
				return false;
		} else if (!thePuzzle.equals(other.thePuzzle))
			return false;
		return true;
	}
}
